<template>
  <div class="watermark-container" ref="watermarkRef">
    <div class="watermark" :style="watermarkStyle"></div>
    <slot></slot>
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'

const props = defineProps({
  width: { type: Number, default: 120 },
  height: { type: Number, default: 64 },
  rotate: { type: Number, default: -22 },
  zIndex: { type: Number, default: 9 },
  image: { type: String, default: '' },
  content: { type: [String, Array], default: '' },
  font: {
    type: Object,
    default: () => ({
      color: 'rgba(0,0,0,.15)',
      fontSize: 16,
      fontWeight: 'normal',
      fontFamily: 'sans-serif',
      fontStyle: 'normal',
      textAlign: 'center',
      textBaseline: 'hanging'
    })
  },
  gap: {
    type: Array,
    default: () => [100, 100]
  },
  offset: {
    type: Array,
    default: () => [50, 50]
  }
})

const watermarkRef = ref(null)
const watermarkStyle = ref({})

const createWatermark = () => {
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  const [gapX, gapY] = props.gap
  const [offsetX, offsetY] = props.offset
  const width = props.width + gapX
  const height = props.height + gapY
  canvas.width = width
  canvas.height = height

  if (props.image) {
    // 图片水印
    const img = new window.Image()
    img.crossOrigin = 'anonymous'
    img.referrerPolicy = 'no-referrer'
    img.onload = () => {
      ctx.clearRect(0, 0, width, height)
      ctx.save()
      ctx.translate(props.width / 2 + offsetX, props.height / 2 + offsetY)
      ctx.rotate((props.rotate * Math.PI) / 180)
      ctx.drawImage(img, -props.width / 2, -props.height / 2, props.width, props.height)
      ctx.restore()
      setStyle(canvas)
    }
    img.src = props.image
  } else {
    // 文本水印
    ctx.clearRect(0, 0, width, height)
    ctx.save()
    ctx.translate(props.width / 2 + offsetX, props.height / 2 + offsetY)
    ctx.rotate((props.rotate * Math.PI) / 180)
    ctx.font = `${props.font.fontStyle} ${props.font.fontWeight} ${props.font.fontSize}px ${props.font.fontFamily}`
    ctx.fillStyle = props.font.color
    ctx.textAlign = props.font.textAlign
    ctx.textBaseline = props.font.textBaseline
    const lines = Array.isArray(props.content) ? props.content : [props.content]
    lines.forEach((line, i) => {
      ctx.fillText(line, 0, i * props.font.fontSize * 1.2)
    })
    ctx.restore()
    setStyle(canvas)
  }
}

function setStyle(canvas) {
  const backgroundImage = canvas.toDataURL('image/png')
  watermarkStyle.value = {
    position: 'absolute',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%',
    pointerEvents: 'none',
    backgroundImage: `url(${backgroundImage})`,
    backgroundRepeat: 'repeat',
    zIndex: props.zIndex
  }
}

onMounted(() => {
  createWatermark()
})

watch(
  [
    () => props.content,
    () => props.image,
    () => props.width,
    () => props.height,
    () => props.rotate,
    () => props.zIndex,
    () => props.font,
    () => props.gap,
    () => props.offset
  ],
  () => {
    createWatermark()
  },
  { deep: true }
)
</script>

<style scoped>
.watermark-container {
  position: relative;
  width: 100%;
  height: 100%;
}

.watermark {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
</style>